/*
* 构造函数: Touchscroll
* 功能: 实现竖向触摸滑动
* 参数:  container       //包裹元素 选择器字符串
*       content         //滚动元素 选择器字符串
*       options{
*           backgroundColor          //滚动条的背景颜色 , 默认为 rgba(0,0,0,0.6)
*           width                    //滚动条的宽度 , 默认为 6px
*       }
* 使用示例: new Touchscroll("#container",".wrapper",{
*               width: 4,
*               backgroundColor: 'rgb(228,228,228)'
*          });
*   <div id="container">
*        <div class="wrapper"></div>
*   </div>
* 缺点: 需要手动设置包裹元素的 position: relative  height  overflow: hidden
* 依赖: transformCSS.js
*       tweenAnimation.js
*
* */
function Touchscroll(container,content,options){
    var app = document.querySelector(container);
    var main = app.querySelector(content);
    var scrollBar = null;

    /*//测试
    var html ='';
    for(var i = 0;i <= 100;i++){
        html += i +'<br>';
    }
    content.innerHTML = html;*/

    app.addEventListener("touchstart",function(e){
        //获取触摸开始时的时间
        this.touchstartTime = Date.now();
        //获取开始时的触点位置
        this.touchY = e.changedTouches[0].clientY;
        //获取触摸开始时 content 的 translateY 的值
        this.contentT = transformCSS(main,'translateY');
        //即点即停
        if(main.timer && main.timer['translateY']){
            clearInterval(main.timer['translateY']);
        }
        //导航条即点即停
        if(scrollBar.timer && scrollBar.timer['translateY']){
            clearInterval(scrollBar.timer['translateY']);
        }
    });
    app.addEventListener("touchmove",function(e){
        //取消过渡效果
        main.style.transition = "none";
        //获取移动时的触点位置
        this.touchY2 = e.changedTouches[0].clientY;
        //计算 content 应该设置的 translateY 的值
        var t = this.contentT + (this.touchY2 - this.touchY);
        /*橡皮筋效果*/
        //定义缩减系数
        var K = 0.5;
        //边界控制
        if(t >= 0 || t <= app.offsetHeight - main.offsetHeight){
            t = this.contentT + (this.touchY2 - this.touchY) * K;
        }
        //设置 content 的 translateY 的值
        transformCSS(main,'translateY',t);
        /*
        * 滚动条移动
        *       滚动条移动距离 / app 的高度 = content移动距离 / content的高度
        *       注意应该要对 content 移动距离取反
        * */
        //计算 scrollBar 应该移动的距离
        var y = -app.offsetHeight * t / main.offsetHeight;
        //设置 scrollBar 的 translateY 的值
        transformCSS(scrollBar,'translateY',y);
    });
    app.addEventListener("touchend",function(e){
        //获取触摸结束时的时间
        this.touchendTime = Date.now();
        //获取结束时的触点位置
        this.touchY3 = e.changedTouches[0].clientY;
        //计算 content 没有惯性移动时应该设置的 translateY 的值
        var t = this.contentT + (this.touchY3 - this.touchY);

        /*惯性滑动*/
        //定义时间系数
        var T = 100;
        //获取滑动速度
        var v = (this.touchY3 - this.touchY)/(this.touchendTime - this.touchstartTime);
        //计算惯性移动的距离
        var s = v * T;
        //新的 translateY 值
        t += s;
        /*
        //添加过渡效果
        content.style.transition = "all 0.5s cubic-bezier(.02,.42,.47,.74)";
        //移动 content
        transformCSS(content,'translateY',t);
        */
        /*导航条跟随惯性移动*/
        //计算加上惯性移动滚动条移动的距离
        var y = -app.offsetHeight * t / main.offsetHeight;

        /*回弹效果*/
        // 声明变量 , 用于保存变形效果 , 默认为 easeOut
        var type = 'easeOut';
        if(t >= 0){
            t = 0;
            type = 'backEaseOut';
        }else if(t <= app.offsetHeight - main.offsetHeight){
            t = app.offsetHeight - main.offsetHeight;
            type = 'backEaseOut';
        }
        /*
        //修改过渡效果
        content.style.transition = "all 0.5s cubic-bezier(.56,.88,.49,1.25)";
        //移动 content
        transformCSS(content,'translateY',t);
        */
        /*导航条跟随回弹*/
        if(y <= 0){
            y = 0;
            type = 'backEaseOut';
        }else if(y >= app.offsetHeight - scrollBar.offsetHeight ){
            y = app.offsetHeight - scrollBar.offsetHeight;
            type = 'backEaseOut';
        }

        /*
        * 即点即停效果
        *       直接使用 transition 的缺点: 无法即点即停,惯性移动时,触摸元素并滑动会取消过渡效果导致元素直接跳到最终位置
        *       可以使用 tweenAnimation() 函数执行过渡 , 然后在 touchstart 事件中清除定时器以实现即点即停效果
        * 注意:
        *       一定要及时清除定时器 , 不然每触发一次 touchend 事件就会开启一个定时器
        * */
        //获取 content 当前的 translateY 值
        var currentContentY = transformCSS(main,'translateY');
        //移动 content
        tweenAnimation(main,'translateY',currentContentY,t,500,10,type);
        //获取 scrollBar 当前的 translateY 值
        var currentScrollY = transformCSS(scrollBar,'translateY');
        //移动 scrollBar
        tweenAnimation(scrollBar,'translateY',currentScrollY,y,500,10,type);
    });

    /*
    * 滚动条初始化
    *       创建滚动条
    *       为滚动条添加 scroll-bar 类
    *       设置滚动条样式
    *           .scroll-bar{
                    position: absolute;
                    right: 0;
                    top: 0;
                    width: 6px;
                    border-radius: 3px;
                    background-color: rgba(0,0,0,0.6);
                }
    *       将滚动条添加到 包裹元素 中
    * */
    app.init = function(){
        /*创建滚动条*/
        scrollBar = document.createElement("div");
        //添加 scroll-bar 类
        scrollBar.className = "scroll-bar";
        //设置滚动条样式
        scrollBar.style.position = "absolute";
        scrollBar.style.right = 0;
        scrollBar.style.top = 0;
        var scrollBarWidth = options && options.width ? options.width : 6;
        scrollBar.style.width = scrollBarWidth +'px';
        scrollBar.style.borderRadius = "3px";
        var bg = options && options.backgroundColor ? options.backgroundColor : "rgba(0,0,0,0.6)";
        scrollBar.style.backgroundColor = bg;
        //设置滚动条的高度
        //计算滚动条应该设置的高度 滚动条的高度 / app高度 = app高度 / content高度
        var h = (app.offsetHeight * app.offsetHeight) / main.offsetHeight;
        scrollBar.style.height = h +'px';
        //将 scrollBar 添加到容器中
        app.appendChild(scrollBar);
        //给外层包裹元素增加 相对定位
        app.style.position = 'relative';

    };
    window.addEventListener('load', function(){
        app.init();
    });

}